use std::vec;
use lib::{Draw, Screen, Button};
struct Selection {
    width: i32,
    height: i32,
    label: String
}

impl Draw for Selection {
    fn draw(&self) {
        println!("this is Selection, width: {}; height: {}, label: {}", self.width, self.height, self.label);
    }
}
fn main() {
    // 1. rust没有继承的概念; 是通过trait来实现代码复用的, 类似于继承
    // 2. struct 和 enum不能等价于其他语言中的对象, 因为struct仅仅只是定义了类型, 其方法在impl中
    // 和struct是分开的;
    // 3. 如果非要类比, trait有点象其他语言中的"对象", trait是用来抽象共有行为的

    // Box, 可以转移所有权, 可以将数据存储到堆上
    // 以下案例就是转移所有权的案例
    // 如果不使用Box, 那么值会被Copy一份到函数内
    let a = Box::new(5);
    fn process_box(mut a: Box<i32>) {
        *a = 123;
        println!("this is a {}", a)
    }
    process_box(a);
    // println!("a in main {}", a);
    let screen = Screen {
        // Trait对象执行的是动态派发, 与之相对应的就是静态派发, 它在编译阶段就确定了类型
        // 这就是dyn Trait的威力所在, 此时的components可以装不同的类型
        // 但是动态派发会产生额外的开销
        components: vec![
            Box::new(Selection{width: 12, height: 12, label: String::from("hello")}),
            Box::new(Button{width: 12, height: 12, label: String::from("world")}),
        ]
    };
    screen.run();
    // 不过要注意的是Trait对象必须保证对象安全, 想要对象安全,必须做到以下两条:
    // 1. 方法返回类型不是Self
    // 2. 方法中不包含任何泛型类型参数
    trait Clone {
        fn clone(&self) -> Self;
    }
    // struct Screen2 {
    //     components: Vec<Box<dyn Clone>> // 此处就会报错
    // }
}
